// @Author EthanScriptOn
// @Desc
package log

import (
	"gitee.com/fatzeng/srf_switch_basic_components/pool"
	"gitee.com/fatzeng/srf_switch_log/log_define"
	"gitee.com/fatzeng/srf_switch_log/log_filter"
	"gitee.com/fatzeng/srf_switch_log/log_rotation"
	"gitee.com/fatzeng/srf_switch_log/log_task"
	"regexp"
)

// LogCenter Log Center coordinates the lifecycle of logs and distributes, collects, and outputs logs.
type LogCenter struct {
	ruleBindings []*RuleBinding
}

func GenerateLogCenter() *LogCenter {
	return &LogCenter{
		ruleBindings: make([]*RuleBinding, 0),
	}
}

// GenerateRuleBinding Generate LogCenter processable RuleBinding based on LogProfile
func (l *LogCenter) GenerateRuleBinding(profiles []*log_define.LogProfile) (err error) {
	if l.ruleBindings == nil {
		l.ruleBindings = make([]*RuleBinding, 0)
	}
	for _, profile := range profiles {
		rbs := make([]*RuleBinding, 0)
		// Template parsing
		templateBits, err := l.TemplateProcess(profile.Template)
		if err != nil {
			return err
		}
		// The output is tiled
		for _, outPut := range profile.Destinations {
			rbs = append(rbs, &RuleBinding{
				LogLevel:                log_define.LogLevel(profile.Level),
				OutPutTemplate:          templateBits,
				OutPutPath:              outPut.Path,
				OutPutType:              log_define.OutPutType(outPut.Type),
				OutPutValidityRotation:  log_define.LogSnapshotDateBit(outPut.ValidityRotation),
				OutPutMaxFileSize:       outPut.MaxFileSize,
				OutPutMaxFiles:          outPut.MaxFiles,
				OutPutCustomRotationTag: log_rotation.CustomRotationTag(outPut.CustomRotationTag),
				OutPutFileNamePattern:   outPut.FileNamePattern,
			})
		}
		// Rule-based judgment tiling
		tagFilters := make([]log_filter.JudgeTag, 0)
		for _, filter := range profile.Filters {
			if !filter.Active {
				continue
			}
			tagFilters = append(tagFilters, log_filter.JudgeTag(filter.Tag))
		}
		for _, rb := range rbs {
			rb.RulesTag = tagFilters
		}
		l.ruleBindings = append(l.ruleBindings, rbs...)
	}
	return
}

// TemplateProcess Template parsing to generate a processable output format
func (l *LogCenter) TemplateProcess(template string) ([]log_define.LogSnapshotOutBit, error) {
	// Define a regular expression that matches a character before % and %
	pattern := `([^\s]%)`
	re := regexp.MustCompile(pattern)
	templateContent := re.FindAllString(template, -1)
	arrAsBit := make([]log_define.LogSnapshotOutBit, 0)
	for _, templateItem := range templateContent {
		arrAsBit = append(arrAsBit, log_define.LogSnapshotOutBit(templateItem))
	}
	return arrAsBit, nil
}

// Record Log entry
func (l *LogCenter) Record(logSnapshot *LogSnapshot) (err error) {
	collectWorkerPool, err := GetCollectPool()
	if err != nil {
		return
	}
	for _, ruleBinding := range l.ruleBindings {
		ruleBindingTemp := ruleBinding
		// Task submission
		if err = collectWorkerPool.Submit(l.BuildLogTask(ruleBindingTemp, logSnapshot)); err != nil {
			return
		}
	}
	return
}

// BuildLogTask Build a log task lifecycle
func (l *LogCenter) BuildLogTask(ruleBinding *RuleBinding, logSnapshot *LogSnapshot) pool.Task {
	return log_task.GenerateLogUnitTask(ruleBinding, logSnapshot)
}
